package com.github.elliot.gatewaycenter.util;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * 公钥加密 私钥解密
 * 私钥签名 公钥验签
 */
public class RSAEncryptionUtil {

    private static final String ALGORITHM = "RSA";
    private static final String TRANSFORMATION = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
    private static final int KEY_SIZE = 2048; // 最小 2048，推荐 3072 或 4096

    /**
     * 生成 RSA 密钥对
     */
    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);
        keyPairGenerator.initialize(KEY_SIZE);
        return keyPairGenerator.generateKeyPair();
    }

    /**
     * 从 Base64 字符串加载公钥
     */
    public static PublicKey loadPublicKey(String base64PublicKey) throws Exception {
        byte[] decodedKey = Base64.getDecoder().decode(base64PublicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return keyFactory.generatePublic(keySpec);
    }

    /**
     * 从 Base64 字符串加载私钥
     */
    public static PrivateKey loadPrivateKey(String base64PrivateKey) throws Exception {
        byte[] decodedKey = Base64.getDecoder().decode(base64PrivateKey);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return keyFactory.generatePrivate(keySpec);
    }

    /**
     * 导出公钥为 Base64 字符串
     */
    public static String exportPublicKey(PublicKey publicKey) {
        return Base64.getEncoder().encodeToString(publicKey.getEncoded());
    }

    /**
     * 导出私钥为 Base64 字符串
     */
    public static String exportPrivateKey(PrivateKey privateKey) {
        return Base64.getEncoder().encodeToString(privateKey.getEncoded());
    }

    /**
     * 使用私钥加密
     */
    public static String encryptWithPrivateKey(String plaintext, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);

        byte[] encryptedBytes = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    /**
     * 使用公钥加密
     */
    public static String encrypt(String plaintext, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        byte[] ciphertext = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(ciphertext);
    }

    /**
     * 使用私钥解密
     */
    public static String decrypt(String encryptedData, PrivateKey privateKey) throws Exception {
        byte[] decodedData = Base64.getDecoder().decode(encryptedData);

        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        byte[] plaintext = cipher.doFinal(decodedData);
        return new String(plaintext, StandardCharsets.UTF_8);
    }

    /**
     * 使用公钥解密
     */
    public static String decryptWithPublicKey(String encryptedText, PublicKey publicKey) throws Exception {
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, publicKey);

        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }

    /**
     * 使用私钥签名
     */
    public static String sign(String data, PrivateKey privateKey) throws Exception {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(privateKey);
        signature.update(data.getBytes(StandardCharsets.UTF_8));

        byte[] digitalSignature = signature.sign();
        return Base64.getEncoder().encodeToString(digitalSignature);
    }

    /**
     * 使用公钥验证签名
     */
    public static boolean verify(String data, String digitalSignature, PublicKey publicKey) throws Exception {
        Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(publicKey);
        signature.update(data.getBytes(StandardCharsets.UTF_8));

        byte[] signatureBytes = Base64.getDecoder().decode(digitalSignature);
        return signature.verify(signatureBytes);
    }

















    public static void main(String[] args) throws Exception {
        print();
    }

    private static void example() throws Exception {
        // 生成密钥对
        KeyPair keyPair = RSAEncryptionUtil.generateKeyPair();
        String publicKeyStr = RSAEncryptionUtil.exportPublicKey(keyPair.getPublic());
        String privateKeyStr = RSAEncryptionUtil.exportPrivateKey(keyPair.getPrivate());

        System.out.println("公钥: " + publicKeyStr);
        System.out.println("私钥: " + privateKeyStr);

        PublicKey publicKey = keyPair.getPublic();
        // PublicKey publicKey = loadPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtRaqyqI+YvVdghD4WuCizuRVUsfaBpEaaXViWqkrTcFWG+asyPIkSVu8j+e70CgPGaIHefQKetMsan7RWI2T+BsRnK3UGBg+PwpepyIzPqcTOfc3+sCXER3ssf445Wyy5GmaStWKQ9V6Y/5o9waYVKdUXsuJYXqsyPNl0rp0wqFTqMlIzHquKyzaMu3n5KTAyBaXLN73T4wZWuuIc3plThynkk9s/a/hVu7clgm8bPZR+hr/heY4W+XTmTr+xNeaMIrCtjpDRF7p5igUmYLgPtn9BcUq+hZy+HjFaodxwb6WVFQqwmPa5c7rfd9CfB3dNrwTm4rRDf5z0Yh0CHR1YQIDAQAB");
        PrivateKey privateKey = keyPair.getPrivate();
        // PrivateKey privateKey = loadPrivateKey("MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC1FqrKoj5i9V2CEPha4KLO5FVSx9oGkRppdWJaqStNwVYb5qzI8iRJW7yP57vQKA8Zogd59Ap60yxqftFYjZP4GxGcrdQYGD4/Cl6nIjM+pxM59zf6wJcRHeyx/jjlbLLkaZpK1YpD1Xpj/mj3BphUp1Rey4lheqzI82XSunTCoVOoyUjMeq4rLNoy7efkpMDIFpcs3vdPjBla64hzemVOHKeST2z9r+FW7tyWCbxs9lH6Gv+F5jhb5dOZOv7E15owisK2OkNEXunmKBSZguA+2f0FxSr6FnL4eMVqh3HBvpZUVCrCY9rlzut930J8Hd02vBObitEN/nPRiHQIdHVhAgMBAAECggEAFQmIltjJUZq6nbkV+Qy+rTVWejLwb7HctSKnZevgNXy/4abnLMMAlysamUctCO4Wbv5lSvQgYYt1zftkm5p69ahDYAXLrW7nkFBGlbkB5gXn1GSVcsJ76kelLzpe5rw9fg6Ml6P+F4pN2R79l7EC8lasFQUlNRdYylGIYzY5CUEdWlq5Blo01EQ+oBNk5oVRT/5uPIkR/nfQAe2CaZ49qGHIqD/CMAG2+nFcyKFfJn8IPGbMCVTnSjAQ1n/vk3qNvgxeFlnN172cx4cqjmpztybjUDWiUsh+qgzcPqHI/wBCHxrkSeLiRKvIGJFXLhk+m5kVyWOejaINGTqAAKaU9wKBgQDui3HqMGnyFkHI/r82U1fKjpvP8Y/68Xm35dw7YQHpchvBz4H8yUC2A1AFju6sEQSesS2UUY5m0k6YiP8ct2FsZsjVQW6VmYVFv0DVmTG2ine0iT2kjw13Vld2O4vIQOelaeAnBvhnpIg+JSepQagP8j7VvyYYNkjqP8M1aFwoxwKBgQDCVuuw9BYkYsGlPd2XmHSPbIwJY5SSGJOVZiWQ2tVyPRieRjFn8OtphtGwej9ecIzAd8gy1CU59InL/+IaZK3e0U1yoq4MeFkClOQMhzONWOewgCEFDPoJ43p9A5KmB8QfwmOgT92zdYbfxYLmkRRRSFUulFbe5aSZg8vTx0xYlwKBgFnyqtmrt8dZLSUlKeTKOGhgrdATPj9ZnpQBULHzOk1UgbLrFBDFsmjvhtURuF2ZbSyJkq5CsneDBa/uuIOTgmDlwQToz1IJuX87Rq9EPMKgI9MnjN7oMiO1ovUqLuMr1i1BZwxQTIqIN/d2+yWPZFfe+GKQ2UR387agpHMXDukxAoGAIpTxD+X/Yq4oI01k9yrr4vG/4ZPUxkKVUIqCuMoYHWH91XxMImDeo0KYYbz/NcD1avJlr5XMogl/08tO4r9zqSi5jWKhchqgTDNOeWQ9qjNd1yyVs55hiAzwqPpPyDetkLE4pThRDTQmsf8lkf3TDbu/XLCM3NEkfyTSyna2gTUCgYBBq/1ncGUMvlc5DyM6WYlQEs7rA1kNvzKDyv5kvjwReCAcAYj8J6tE70KcvrD6vKa7AVkZuW/rVzrugT+lmPDyuJbILE7WRoPCacRPxpeng3U9X3YzonnE6/9vv61PsD4XhL1Q4E0szqoJ+k0oznkqmAvlSbZp+eI3egMgh7QoBQ==");


        // 加密
        String plaintext = "这是敏感数据";
        String encrypted = RSAEncryptionUtil.encrypt(plaintext, publicKey);
        System.out.println("加密结果: " + encrypted);

        // 解密
        String decrypted = RSAEncryptionUtil.decrypt(encrypted, privateKey);
        System.out.println("解密结果: " + decrypted);

        // 签名和验证
        String data = "需要签名的数据";
        String signature = RSAEncryptionUtil.sign(data, privateKey);
        boolean isValid = RSAEncryptionUtil.verify(data, signature, publicKey);
        System.out.println("签名验证: " + isValid);
    }

    private static String jsonString = "{\"data\":\"bDknWqQqjwX429wAgsh7r1WtyW46slPDZuqm1bFjXrpCuA8eDaDtTW6YTrPfZWlr9gVPU/n6JvMebSknDn+0H1LsnCZX0Bg+oAYPelWH8i7cuoY+71Un94WyPX03BLaRm6jXNn51UJqBXZKqV3EIM3IU3k/gghSjuaGGKAa5kUXWnftIWZgtDXr8fJKKjQPd2I+1otkS3R09cC5fOHMJrqxi/deEzw1nT4XuOFsKMu2MxJsCYBB34FM505UQBh0Qx9MA2nL0QffNYepuXl6ilSTqM+ZTS2ysnnJdhqjA6zuKK9/uw4JqwbVBWBF31fhzURcamIGe9nnMWAD82hdUTg==\",\"sign\":\"PGdhcubY+pT9cQsoJH0foFtSugmc7VpWcfXotCSF9GYiZ1tKxi3eQyGN7p6vmMUftkbG2V/wBj8auaJo0RsmL1iJQAP260TcuLPj8s5qF4B2uxc0xt2bKWMK/LL/Rrn2gFhWIVpcht3bSWNLn4jxqjzfijoLNOhcV0EWcFCxorDEFXE0jYKvPsDkrFsnLAt+fYK8mIc/Q6Ut6+ZWZb0roPVLm5NHDnnhnJaAcVlZ364iPxb4zOjYBe731ZTmVV5GruQM0xr545oYI0bMyctx7Rpy+qBCCrBgxR+qcYkrldTkd9KS+oCRcShUsio1wp0L990LYCy7ipCuOnv0RCmiAA==\"}";

    private static void print() throws Exception {

        PublicKey publicKey = loadPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtRaqyqI+YvVdghD4WuCizuRVUsfaBpEaaXViWqkrTcFWG+asyPIkSVu8j+e70CgPGaIHefQKetMsan7RWI2T+BsRnK3UGBg+PwpepyIzPqcTOfc3+sCXER3ssf445Wyy5GmaStWKQ9V6Y/5o9waYVKdUXsuJYXqsyPNl0rp0wqFTqMlIzHquKyzaMu3n5KTAyBaXLN73T4wZWuuIc3plThynkk9s/a/hVu7clgm8bPZR+hr/heY4W+XTmTr+xNeaMIrCtjpDRF7p5igUmYLgPtn9BcUq+hZy+HjFaodxwb6WVFQqwmPa5c7rfd9CfB3dNrwTm4rRDf5z0Yh0CHR1YQIDAQAB");
        PrivateKey privateKey = loadPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXhG0yOfbEHdBkRmfCgbsT+38HibrjeTZIt0Xqa2mqMfOKHdPK271cbJtvm7AgwYOQOfp0PlY9MQ9ihRdOFyE6DqKbXCXzKIWOAyMLSTqUxata/egr6FgEOPT1F+XhrD87ht6W0lU5YIGQV8ak8Md9nI1XQzpyNiQRccnmrC9l8uQbDnU05RFuwo0CX/AyBBKavHkHLTFUAIw9J0U/VTnQe8Mq/3khIxkoIQ6Vd8g6KheQyo/VbYT96W8BzjYsXWltdMsnVNEqDSPWCquzV1+4K6thOAYFuw3S/vjIRviOhUTfJEnoalz4JpguUNQSrQb45ksBltzI1SyJQ52pQLGDAgMBAAECggEAA8kpx07+dPD/w3mk3w3JxFqM1n3g/w0Ix7FYnF5Zsgh0etd68r8h0JzgF15O/MqJBIIGWYAzPG0s4rvLlMZsLJywAGzBf/1btOwsJHyMa6oyuV/NvMcd5+EaccNKmaRpog2hIyiXO4tHQXmH+5gOi/ts5qjF3ZOvvAXZUxurRYNNxWDptOjIpa6KVeAbEl8+iDTUqs+91q7mngt0SxBz6s+UtfxJHPDjTCptOxAqGZhL/rV+UOP694LwvvMtC1V5OCXn/mZhnygEsMneN0pd7pwtpzv3C/LFNguDp24FwqRcweYVV4j4Ka6A6hipUnoSZS1pJ3EA+YFE0UUWOFTLiQKBgQDS0/6GCaLTgJr0lRu3mrqor0tr1v2w0JgR8S/n+qab5nBKuj6gUmo5rnXtAGGHM5WMeP03Dr6lclchn3yYoDbt9yI7bxrUfKI67IT88DXCZhyURFUx8nirccUMBxgZ0f9pFsvygSxk9H8Rr+kN3n/IIKBJz0IIcRVycQYGZpEi+QKBgQC3+zXpGYQg73RGhR3tUZb4qX1D9jL/ADRy9RxI8RUFDgCaCtKnXrUVZxuNiKyzqFNqVvaxl9Bt9+0/4M6HWKKGxwzkP94O4njE/DH2zuv030qI8GPW+yJPffTzGFAPzNc/P+OFWPeCMQtArJc8IzsZ6RwiDN0+4mF78fQJUgEbWwKBgCIQaLaFhg6AYAkWsoTG9lPdBuWkthbEjV2Qx7nGsPbNk+UvFIFY75rkSl+ByUBMIGSzA87KjhkzUUq4dyw97sIiRSCvQfmFLb0xjAdGVJlVYFbAd7d7Qu4IktrvpoA9gvQa39cN8ftZ2dIkxxYbli/ivaNPXo74nouAIYYVOmwZAoGBAJXq6vwd4a/gz5PjRwap9GZ93egyR03JQfPmzXyWjnVG+rCLXyopH0/oa+hB1dCzuf0uDema9qmVXEswCbr6O72tl1CqxmzEmHqTsrcV1+n6xcaedAyrKUMzNRWd2yd02HTev6xaWZ1KD4xM1xOW9cLgVB9e8i4a1Crmdt/dZa9/AoGAaP9OZwDUAGZlkfYa9ahYfxIgXgQEPHskFCSS3+95aiEGZgqOJoVrCGJwEJj9xqD5AP1WSsi4Z23w6rfTdrwUFrwUDj1eFJ3VgbJgeqYHaoE+y+jSEuB0u3c+GFvn4Hd2p4I+oNm1a9Il/NckL9tiYTNDcmnfRtcLFwdkwz7bDvQ=");

        JSONObject jsonObject = JSON.parseObject(jsonString);
        String date = jsonObject.get("data").toString();
        String sign = jsonObject.get("sign").toString();

        String decrypt = decrypt(date, privateKey);
        System.out.println("解密结果: " + decrypt);

        boolean verify = verify(date, sign, publicKey);
        System.out.println("签名验证: " + verify);
    }
}
